package com.luoruihang.logstatementgenerator.domain.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.luoruihang.logstatementgenerator.domain.infrastructure.http.LlmHttpUtils;
import com.luoruihang.logstatementgenerator.domain.model.ActionContext;
import com.luoruihang.logstatementgenerator.domain.model.LlmRequest;
import com.luoruihang.logstatementgenerator.domain.model.LlmResponse;
import com.luoruihang.logstatementgenerator.domain.model.LlmResult;
import com.luoruihang.logstatementgenerator.domain.model.llmresponseformat.GlmResponse;
import com.luoruihang.logstatementgenerator.domain.service.AbstractGenerateLogStatement;
import netscape.javascript.JSObject;

import java.util.List;
import java.util.Map;

public class GenerateLogStatementImpl extends AbstractGenerateLogStatement {

	public GenerateLogStatementImpl() {
	}

	@Override
	protected ActionContext constructActionContext(Project project, DataContext context, Editor editor) {
		// 包装ActionContext
		return new ActionContext(project,context,editor);
	}

	/**
	 * 将选中的文本及其他需要的信息包装成请求参数
	 *
	 * @param context
	 * @return
	 */
	@Override
	protected LlmRequest getLlmRequestParams(ActionContext context) {
		Editor editor = context.getEditor();
		// 获取选中文本
		String selectedText = editor.getSelectionModel().getSelectedText();
		/*
		包装：
		{
		"model":"glm-4",
		"messages":[
				{"role":"user","content":"generate a log statement about code as follows:{selectedText}
			]
		}
		 */
		LlmRequest llmRequestParams = new LlmRequest();
		llmRequestParams.setModel("glm-4");
		llmRequestParams.addMessage("user", selectedText);
		return llmRequestParams;
	}

	/**
	 * 向外部请求，同步或异步请求，决定了最后得到最终结果的方式
	 *
	 * @param llmRequestParams
	 * @return
	 */
	@Override
	protected LlmResponse getLlmResponse(LlmRequest llmRequestParams, ActionContext context) {
		String result = LlmHttpUtils.doPost(llmRequestParams);
		// 根据需要构造不同的model并解析，这里仙构造Glm的响应并解析
		GlmResponse glmResponse = JSONObject.parseObject(result, GlmResponse.class);

		LlmResponse llmResponse = new LlmResponse();
		llmResponse.setResponseText(glmResponse.getChoices().get(0).getMessage().getContent());
		return llmResponse;
	}

	/**
	 * 若为同步请求，直接从response结果中得到相应代码
	 * 若为异步请求，则从response中得到id任务单，轮询请求在最终结果
	 * 最后包装成LlmResult，包括生成的日志语句主体，位置等
	 *
	 * @param llmResponse
	 * @return
	 */
	@Override
	protected LlmResult getLlmResult(LlmResponse llmResponse, ActionContext context) {
		LlmResult llmResult = new LlmResult();
		llmResult.setLogStatement(llmResponse.getResponseText());
		// TODO 临时设置生成日志语句的行数为光标下一行, 暂时不用这个属性，看日志位置具体如何确定
		llmResult.setLocationLineNumber(context.getEditor().getSelectionModel().getSelectionEndPosition().line + 1);
		return llmResult;
	}

	/**
	 * 根据得到的结果，在指定位置生成指定的日志语句，有必要时生成导包语句
	 *
	 * @param llmResult
	 */
	@Override
	protected void generateLogStatement(LlmResult llmResult, ActionContext context) {
		int lineNumber = llmResult.getLocationLineNumber();
		String logStatement = llmResult.getLogStatement();

		Editor editor = context.getEditor();
		Document document = editor.getDocument();

		Application application = ApplicationManager.getApplication();
		// 插入要生成的代码
		application.runWriteAction(new Runnable() {
			@Override
			public void run() {
				int start = editor.getSelectionModel().getSelectionStart();
				int end = editor.getSelectionModel().getSelectionEnd();
				WriteCommandAction.runWriteCommandAction(context.getProject(), new Runnable() {
					@Override
					public void run() {
						// TODO 日志语句如果使用了当前未导入的日志类，还需要进行导入语句的生成

						// 将选中的代码字段替换为带上日志语句的代码字段
						document.replaceString(start, end, logStatement);
					}
				});
			}
		});


	}
}
